#include <typescommon.h>
#include <errno.h>
#include <stdarg.h>
#include <genrand.h>

// 指针封装。
// gcc不支持引用。
#if 0
#include <stateMachine.h>
enum MY_CHECK_STATE_ENUM
{
    MY_CHECK_STATE_0 = 0,
    MY_CHECK_STATE_1,
    MY_CHECK_STATE_2,
    MY_CHECK_STATE_3,
    MY_CHECK_STATE_4,
    MY_CHECK_STATE_5,
    MY_CHECK_STATE_6,
};
int stateMachineCheckInit(struct stateMachineBaseInform *thisState)
{
    logdebug("init %d", thisState->stateId);
    switch (thisState->stateId)
    {
    case MY_CHECK_STATE_0:
    {
        stateMachineManagerTransition(thisState->stateManager, MY_CHECK_STATE_1);
        break;
    }
    default:
        break;
    }
    return 0;
}
int stateMachineCheckRun(struct stateMachineBaseInform *thisState)
{
    logdebug("run %d", thisState->stateId);
    switch (thisState->stateId)
    {
    case MY_CHECK_STATE_1:
    {
        stateMachineManagerTransition(thisState->stateManager, MY_CHECK_STATE_2);
        break;
    }
    case MY_CHECK_STATE_3:
    {
        stateMachineManagerTransition(thisState->stateManager, MY_CHECK_STATE_0);
        stateMachineManagerQuit(thisState->stateManager);
        break;
    }
    default:
        break;
    }
    return 0;
}
int stateMachineCheckQuit(struct stateMachineBaseInform *thisState)
{
    logdebug("quit %d", thisState->stateId);
    switch (thisState->stateId)
    {
    default:
        break;
    }
    return 0;
}

int stateMachineCheck2Init(struct stateMachineBaseInform *thisState)
{
    logdebug("init %d", thisState->stateId);
    return 0;
}
int stateMachineCheck2Run(struct stateMachineBaseInform *thisState)
{
    logdebug("run %d", thisState->stateId);
    stateMachineManagerTransition(thisState->stateManager, MY_CHECK_STATE_3);
    return 0;
}
int stateMachineCheck2Quit(struct stateMachineBaseInform *thisState)
{
    logdebug("quit %d", thisState->stateId);
    stateMachineManagerTransition(thisState->stateManager, MY_CHECK_STATE_0);
    return 0;
}

struct stateMachineManagerInform myCheckStateMnger;

struct stateMachineBaseInform myCheckStates[] = {
    stateMachineBaseDeine(stateMachineCheckInit, stateMachineCheckRun, stateMachineCheckQuit, MY_CHECK_STATE_0, &myCheckStateMnger),
    stateMachineBaseDeine(stateMachineCheckInit, stateMachineCheckRun, NULL, MY_CHECK_STATE_1, &myCheckStateMnger),
    stateMachineBaseDeine(NULL, stateMachineCheck2Run, stateMachineCheck2Quit, MY_CHECK_STATE_2, &myCheckStateMnger),
    stateMachineBaseDeine(stateMachineCheckInit, stateMachineCheckRun, stateMachineCheckQuit, MY_CHECK_STATE_3, &myCheckStateMnger),
};

int main()
{
    int tmpflag = 0;
    stateMachineManagerInit(&myCheckStateMnger, NULL, myCheckStates, ARRAY_LEN(myCheckStates), MY_CHECK_STATE_0);
    while (1)
    {
        tmpflag = stateMachineManagerRun(&myCheckStateMnger);
        if(tmpflag < 0)
        {
            break;
        }
        usleep(1000 * 1000);
    }
}

#endif

#if 1
#include <protocolProcesser.h>
#include <charQueue.h>
#include <commandList.h>
#include <commandSetReadSN.h>
#include <pthread.h>
#include <threadExcuter.h>
#include <deviceNormalParam.h>
#include <commandReadBaseInform.h>
#include <deviceOperateSN.h>

struct checkMasterCommandPcStruct
{
    uint8_t queueSaveBuffer[2000];
    struct queueArrayInformStruct fifoInput;

    struct protocolProcessorInform commandDevider;
    uint8_t deviceDealId[DEVICE_SERIAL_NUMBER_SIZE];
};

struct threadExcuterInform deviceThread;
struct checkDeviceCommandPcStruct
{
    struct protocolProcessorInform commandDevider;

    uint8_t queueSaveBuffer[2000];
    struct queueArrayInformStruct fifoInput;
    // uint8_t deviceAddr;
};

#define DEVICE_CHECK_MAX_NUMBER 1
struct checkMasterCommandPcStruct mastercommand;
struct checkDeviceCommandPcStruct devicecommand[DEVICE_CHECK_MAX_NUMBER];

int masterCommandReceiveRemoteCheck(uint8_t *readbuffer, int readsize, void *userdata)
{
    struct checkMasterCommandPcStruct *tmpmaster = (struct checkMasterCommandPcStruct *)userdata;
    if (!tmpmaster)
    {
        logerror("");
        return -1;
    }
    return queueArrayGetString(&tmpmaster->fifoInput, readbuffer, readsize);
}
int masterCommandSendRemoteCheck(const uint8_t *sendbuffer, int sendsize, void *userdata)
{
    struct checkMasterCommandPcStruct *tmpmaster = (struct checkMasterCommandPcStruct *)userdata;
    if (!tmpmaster)
    {
        logerror("");
        return -1;
    }
    {
        uint8_t tmpshowstring[PROTOCOL_PACK_MAX_SIZE * 2];
        int tmpconvertSize = hexBufferToReadableString((const char *)sendbuffer, sendsize, (char *)tmpshowstring, sizeof(tmpshowstring), 0);
        logdebug("send,size=%d,convet size=%d,hex str=%s", sendsize, tmpconvertSize, tmpshowstring);
    }
#if 1
    for (int i = 0; i < ARRAY_LEN(devicecommand); i++)
    {
        queueArrayInputString(&devicecommand[i].fifoInput, sendbuffer, sendsize);
    }
    return sendsize;
#else
    if (!(tmpmaster->deviceDealId < ARRAY_LEN(devicecommand)))
    {
        logerror("%d", tmpmaster->deviceDealId);
        return -1;
    }
    return queueArrayInputString(&devicecommand[tmpmaster->deviceDealId].fifoInput, sendbuffer, sendsize);
#endif
}

int deviceCommandReceiveRemoteCheck(uint8_t *readbuffer, int readsize, void *userdata)
{
    struct checkDeviceCommandPcStruct *tmpdevice = (struct checkDeviceCommandPcStruct *)userdata;
    if (!tmpdevice)
    {
        logerror("");
        return -1;
    }
    // logdebug("%d", queueArraySize(&tmpdevice->fifoInput));
    return queueArrayGetString(&tmpdevice->fifoInput, readbuffer, readsize);
}
int deviceCommandSendRemoteCheck(const uint8_t *sendbuffer, int sendsize, void *userdata)
{
    {
        uint8_t tmpshowstring[PROTOCOL_PACK_MAX_SIZE * 2];
        int tmpconvertSize = hexBufferToReadableString((const char *)sendbuffer, sendsize, (char *)tmpshowstring, sizeof(tmpshowstring), 0);
        logdebug("send,size=%d,convet size=%d,hex str=%s", sendsize, tmpconvertSize, tmpshowstring);
    }
    return queueArrayInputString(&mastercommand.fifoInput, sendbuffer, sendsize);
}

void *deviceCheckRunFunction(void *data)
{
    struct threadExcuterInform *tmpthread = (struct threadExcuterInform *)data;
    struct protocolCommandCommunicateInform tmpCommunity;
    struct hashCommandActuatorManage tmpCommandMng;
    // memcpy(devNorParmInst()->deviceSerialNumber, "12345678901234567890123456789012", sizeof(devNorParmInst()->deviceSerialNumber));

    for (int i = 0; i < ARRAY_LEN(devicecommand); i++)
    {
        // check device, need malloc command space for every device.
        struct hashCommandActuatorInform *tmpDeviceCmd = (struct hashCommandActuatorInform *)malloc(sizeof(struct hashCommandActuatorInform) * commandIdMaxSize);
        memcpy(tmpDeviceCmd, deviceCommandReceiveCallbackBuffer, sizeof(struct hashCommandActuatorInform) * commandIdMaxSize);
        queueArrayInit(&devicecommand[i].fifoInput, devicecommand[i].queueSaveBuffer, sizeof(devicecommand[i].queueSaveBuffer));
        hashCommandActuatorInit(&tmpCommandMng, tmpDeviceCmd, commandIdMaxSize);
        memset(tmpCommunity.deviceSerialNumber, 0x00, sizeof(tmpCommunity.deviceSerialNumber));
        tmpCommunity.deviceSerialNumber[0] = i + 1;
        tmpCommunity.receiveFunction = deviceCommandReceiveRemoteCheck;
        tmpCommunity.sendFunction = deviceCommandSendRemoteCheck;
        tmpCommunity.userdata = &devicecommand[i];
        protocolProcessorInit(&devicecommand[i].commandDevider, tmpCommunity, tmpCommandMng);
    }
    logdebug("");
    while (tmpthread->threadRunflag)
    {
        for (int i = 0; i < ARRAY_LEN(devicecommand); i++)
        {
            protocolProcessorRunReceive(&devicecommand[i].commandDevider);
        }
        usleep(50 * 1000);
    }

    for (int i = 0; i < ARRAY_LEN(devicecommand); i++)
    {
        free(devicecommand[i].commandDevider.protocolCommandMng.commandHash);
    }

    logdebug("thread end");
    return NULL;
}

int main()
{
    struct protocolCommandCommunicateInform tmpCommunity;
    struct hashCommandActuatorManage tmpCommandMng;
    int tmpflag;
    queueArrayInit(&mastercommand.fifoInput, mastercommand.queueSaveBuffer, sizeof(mastercommand.queueSaveBuffer));
    hashCommandActuatorInit(&tmpCommandMng, masterCommandReceiveCallbackList, commandIdMaxSize);
    memset(tmpCommunity.deviceSerialNumber, 0xff, sizeof(tmpCommunity.deviceSerialNumber));
    tmpCommunity.receiveFunction = masterCommandReceiveRemoteCheck;
    tmpCommunity.sendFunction = masterCommandSendRemoteCheck;
    tmpCommunity.userdata = &mastercommand;
    tmpCommunity.commandWaitTimeoutMs = 200;
    tmpCommunity.retryMaxTime = 0;
    protocolProcessorInit(&mastercommand.commandDevider, tmpCommunity, tmpCommandMng);

    deviceSnReadFormHardware();
    deviceParamReadFromHard(devParamNormalOpt()); // init param
    deviceNormalParamPrint();

    threadExcuterInit(&deviceThread, deviceCheckRunFunction, NULL);
    threadExcuterBegin(&deviceThread);

    memset(mastercommand.deviceDealId, 0, sizeof(mastercommand.deviceDealId));
    mastercommand.deviceDealId[0] = 1;
    usleep(100 * 1000);
    do
    {
        if (mastercommand.deviceDealId[0] > ARRAY_LEN(devicecommand))
        {
            break;
        }
#if 1
        logdebug("addr %s,begin", getMaxSizeHexStr(mastercommand.deviceDealId).byteStr);
        struct masterStructSetReadSN tmpread;
        generatorRandString_Aa1((char *)tmpread.setSn, sizeof(tmpread.setSn));
        tmpflag = masterWaitResponseSetReadSN(&mastercommand.commandDevider, &tmpread, sizeof(struct masterStructSetReadSN),
                                                mastercommand.deviceDealId);
        logdebug("addr %s,result=%d", getMaxSizeHexStr(mastercommand.deviceDealId).byteStr, tmpflag);

        struct masterStructReadBaseInfo tmpBaseCmd;
        tmpflag = masterWaitResponseReadBaseInfo(&mastercommand.commandDevider, &tmpBaseCmd, sizeof(struct masterStructReadBaseInfo),
                                                tmpread.setSn);
        logdebug("addr %s,result=%d", getMaxSizeHexStr(mastercommand.deviceDealId).byteStr, tmpflag);
#else
        logdebug("addr %s,begin", getMaxSizeHexStr(mastercommand.deviceDealId).byteStr);
        // struct masterStructSetReadSN tmpread;
        // generatorRandString_Aa1((char *)tmpread.setSn, sizeof(tmpread.setSn));
        // tmpflag = masterWaitResponseSetReadSN(&mastercommand.commandDevider, &tmpread, sizeof(struct masterStructSetReadSN),
        //                                         mastercommand.deviceDealId);
        // logdebug("addr %s,result=%d", getMaxSizeHexStr(mastercommand.deviceDealId).byteStr, tmpflag);

        struct masterStructReadBaseInfo tmpBaseCmd;
        tmpflag = masterWaitResponseReadBaseInfo(&mastercommand.commandDevider, &tmpBaseCmd, sizeof(struct masterStructReadBaseInfo),
                                                 mastercommand.deviceDealId);
        logdebug("addr %s,result=%d", getMaxSizeHexStr(mastercommand.deviceDealId).byteStr, tmpflag);
        if (tmpflag >= 0)
        {
            struct deviceStructReadBaseInfo *tmpResponse = (struct deviceStructReadBaseInfo *)mastercommand.commandDevider.commandExcuterResponse;

            logdebug("version: %s, sn: %s, type=%d", tmpResponse->version,
                     getMaxSizeHexStr(tmpResponse->serialnumber).byteStr, tmpResponse->deviceType);
        }
#endif
        mastercommand.deviceDealId[0]++;
    } while (1);
    threadExcuterQuit(&deviceThread);
    return 0;
}
#endif

#if 0
#include <deviceNormalParam.h>

struct deviceParameterNormalInformOld
{
    struct
    {
        uint16_t paramSize;
        uint16_t paramCrc;
    };
    uint8_t deviceSerialNumber[DEVICE_SERIAL_NUMBER_SIZE]; // config by broadcast
};

struct deviceParameterNormalInformNew
{
    struct
    {
        uint16_t paramSize;
        uint16_t paramCrc;
    };
    uint8_t deviceSerialNumber[DEVICE_SERIAL_NUMBER_SIZE]; // config by broadcast
    uint8_t device485Addr;                                  // config by broadcast with device serial number
    uint8_t deviceip[4];
};

int main()
{
    struct deviceParameterNormalInformOld tmpparmOld;
    struct deviceParameterNormalInformNew tmpparmNew;
    char *tmpConstStr;
    // struct deviceParameterNormalInform *tmpNormalParam = devNorParmInst();
    logdebug("--------check read");
    deviceParamReadFromHard(devParamNormalOpt());
    deviceNormalParamPrint();
    logdebug("-------check write");
    deviceParamWriteToHard(devParamNormalOpt());
    deviceNormalParamPrint();
    logdebug("-------check modify");
    tmpConstStr = "12345678901234567890123456789012";
    memcpypro(devNorParmInst()->deviceSerialNumber, sizeof(devNorParmInst()->deviceSerialNumber), tmpConstStr, strlen(tmpConstStr));
    devNorParmInst()->device485Addr = 0x02;
    deviceNormalParamPrint();
    logdebug("-------check write new");
    deviceParamWriteToHard(devParamNormalOpt());
    deviceNormalParamPrint();
    logdebug("-------check new data");
    deviceParamReadFromHard(devParamNormalOpt());
    deviceNormalParamPrint();
    logdebug("-------check reset 1");
    deviceParamResetAndSave(devParamNormalOpt(), DEVICE_PARAM_CONFIG_LEVEL_1);
    deviceNormalParamPrint();
    logdebug("-------check reset 0");
    deviceParamResetAndSave(devParamNormalOpt(), DEVICE_PARAM_CONFIG_LEVEL_0);
    deviceNormalParamPrint();

    devNorParmInst()->device485Addr = 0x01;
    tmpConstStr = "ab345678901234567890123456789012";
    memcpypro(tmpparmOld.deviceSerialNumber, sizeof(tmpparmOld.deviceSerialNumber), tmpConstStr, strlen(tmpConstStr));
    tmpparmOld.paramSize = sizeof(tmpparmOld) - offsetof(struct deviceParameterNormalInformOld, deviceSerialNumber);
    tmpparmOld.paramCrc = calculateUint16CrcHash(tmpparmOld.deviceSerialNumber, tmpparmOld.paramSize);
    logdebug("-------check config shorter data");
    logdebug("%d,%d", tmpparmOld.paramSize, tmpparmOld.paramCrc);
    deviceParamOperateConfig(devParamNormalOpt(), &tmpparmOld, 0);
    deviceNormalParamPrint();
    logdebug("-------check write shorter param");
    deviceParamWriteToHard(devParamNormalOpt());
    logdebug("-------check read shorter param");
    deviceParamReadFromHard(devParamNormalOpt());
    deviceNormalParamPrint();

    tmpConstStr = "fffffddddd";
    memcpypro(tmpparmNew.deviceSerialNumber, sizeof(tmpparmNew.deviceSerialNumber), tmpConstStr, strlen(tmpConstStr));
    tmpparmNew.device485Addr = 0x03;
    tmpConstStr = "fffffddddd";
    memcpypro(tmpparmNew.deviceip, sizeof(tmpparmNew.deviceip), tmpConstStr, strlen(tmpConstStr));
    tmpparmNew.paramSize = sizeof(tmpparmNew) - offsetof(struct deviceParameterNormalInformOld, deviceSerialNumber);
    tmpparmNew.paramCrc = calculateUint16CrcHash(tmpparmNew.deviceSerialNumber, tmpparmNew.paramSize);
    logdebug("-------check config longer data");
    logdebug("%d,%d", tmpparmNew.paramSize, tmpparmNew.paramCrc);
    deviceParamOperateConfig(devParamNormalOpt(), &tmpparmNew, 0);
    deviceNormalParamPrint();
    logdebug("-------check write longer param");
    deviceParamWriteToHard(devParamNormalOpt());
    logdebug("-------check read longer param");
    deviceParamReadFromHard(devParamNormalOpt());
    deviceNormalParamPrint();
}
#endif
